home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 6 / CU Amiga Magazine's Super CD-ROM 06 (1996)(EMAP Images)(GB)(Track 1 of 4)[!][issue 1997-01].iso / cucd / online / fidonetts / 3csrc.lzh / 3mailin.c < prev    next >
C/C++ Source or Header  |  1992-05-02  |  15KB  |  503 lines

  1. /* 3mailin.c
  2.  * Public Domain
  3.  *
  4.  * contains functions to read a type 3 ASCII packet
  5.  *
  6.  * code as presented is memory thrifty.  if you've got plenty of memory,
  7.  * here are some performance suggestions:
  8.  *
  9.  *      instead of reading headers a line at a time, read into a
  10.  *      big buffer and parse in memory (32K guarantees getting full
  11.  *      header under "worst" conditions).  use same buffer used for
  12.  *      message text to (normally) prevent reloading message to get
  13.  *      text.
  14.  *
  15.  *  and/or
  16.  *
  17.  *      dynamically adjust size of msg text buffer based on average
  18.  *      size (or most common size) of msgs received to date.
  19.  *
  20.  *
  21.  *  user-callable function:
  22.  *
  23.  *    long process_3pkt (void *anon, char *fname, int *error);
  24.  *
  25.  *      anon = private data for "callback" functions
  26.  *      fname = name of packet to process
  27.  *      error = returned error code
  28.  *      returns number of messages processed
  29.  *
  30.  *    see comments @ function (end of file)
  31.  */
  32.  
  33. #include "3mail.h"
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <io.h>
  38. #include <fcntl.h>
  39. #include <share.h>
  40.  
  41.  
  42.  
  43. int open_3pkt (int i3handle,char *fname, int *error) {
  44.  
  45.   /* open a type 3 packet for input
  46.    * i3handle = file handle in use (or -1 if none)
  47.    * fname = name of packet to open
  48.    * *error = error return code
  49.    */
  50.  
  51.   if(i3handle != -1) close(i3handle);   /* close if already open */
  52.   i3handle = sopen(fname,O_RDONLY | O_BINARY,SH_DENYNO);
  53.   if(i3handle == -1) *error = NOOPEN3;
  54.   return i3handle;
  55. }
  56.  
  57.  
  58. int close_3pkt (int i3handle) { /* close a packet */
  59.  
  60.   if(i3handle != -1) close(i3handle);   /* close if good handle */
  61.   i3handle = -1;                      /* in case you made it global... */
  62.   return i3handle;
  63. }
  64.  
  65.  
  66. PHDR3 * free_3pkthdr (PHDR3 *cpkt) {
  67.  
  68.   /* free dynamically allocated memory of a packet header structure
  69.    * including linked list of TAG3 structures attached, if any
  70.    */
  71.  
  72.   TAG3 *info,*next;
  73.  
  74.   if(cpkt->from) free(cpkt->from);
  75.   if(cpkt->to) free(cpkt->to);
  76.   if(cpkt->creator) free(cpkt->creator);
  77.   if(cpkt->pword) free(cpkt->pword);
  78.   if(cpkt->area) free(cpkt->area);
  79.   if(cpkt->head) {
  80.     info = cpkt->head;
  81.     while(info) {
  82.       next = info->next;
  83.       if(info->tag) free(info->tag);
  84.       if(info->data) free(info->data);
  85.       free(info);
  86.       info = next;
  87.     }
  88.   }
  89.   free(cpkt);
  90.   cpkt = NULL;
  91.   return cpkt;
  92. }
  93.  
  94.  
  95.  
  96. MHDR3 * free_3msghdr (MHDR3 *cmsg) {
  97.  
  98.   /* free dynamically allocated memory of a message header structure
  99.    * including linked list of TAG3 structures attached, if any
  100.    */
  101.  
  102.   TAG3 *info,*next;
  103.  
  104.   if(cmsg->from) free(cmsg->from);
  105.   if(cmsg->to) free(cmsg->to);
  106.   if(cmsg->subj) free(cmsg->subj);
  107.   if(cmsg->date) free(cmsg->date);
  108.   if(cmsg->area) free(cmsg->area);
  109.   if(cmsg->id) free(cmsg->id);
  110.   if(cmsg->ref) free(cmsg->ref);
  111.   if(cmsg->head) {
  112.     info = cmsg->head;
  113.     while(info) {
  114.       next = info->next;
  115.       if(info->tag) free(info->tag);
  116.       if(info->data) free(info->data);
  117.       free(info);
  118.       info = next;
  119.     }
  120.   }
  121.   free(cmsg);
  122.   cmsg = NULL;
  123.   return cmsg;
  124. }
  125.  
  126.  
  127. PHDR3 * create_3pkthdr (void) {
  128.  
  129.   /* create an empty PHDR3 pkt header structure
  130.    * returns a pointer to the PHDR3 structure created
  131.    */
  132.  
  133.   PHDR3 *info;
  134.  
  135.   info = (PHDR3 *)malloc(sizeof(PHDR3));
  136.   if(info) {
  137.     info->from = info->to = info->creator = info->pword = info->area = NULL;
  138.     info->head = NULL;
  139.   }
  140.   return info;
  141. }
  142.  
  143.  
  144. MHDR3 * create_3msghdr (void) {
  145.  
  146.   /* create an empty MHDR3 msg header structure
  147.    * returns a pointer to the MHDR3 structure created
  148.    */
  149.  
  150.   MHDR3 * info;
  151.  
  152.   info = (MHDR3 *)malloc(sizeof(MHDR3));
  153.   if(info) {
  154.     info->from = info->to = info->subj = info->date = info->id =
  155.       info->ref = info->area = NULL;
  156.     info->head = NULL;
  157.   }
  158.   return info;
  159. }
  160.  
  161.  
  162. PHDR3 * read_3pkthdr (int i3handle, PHDR3 *cpkt, int *error) {
  163.  
  164.   /* could use more error & grunge checking
  165.    * returns NULL on error OR EOP
  166.    * *error may contain more info
  167.    * fills in cpkt from file represented by i3handle
  168.    */
  169.  
  170.   char   s[257];
  171.  
  172.   *error = NOTPKT3;
  173.   if(cpkt) free_3pkthdr(cpkt);
  174.   if(fgets3(s,256,i3handle)) {
  175.     if(!strcmp(s,ASCII3ID)) {
  176.       *error = BADPKTHDR3;
  177.       cpkt = create_3pkthdr();
  178.       if(cpkt) {
  179.         if(fgets3(s,256,i3handle)) {
  180.           cpkt->from = strdup3(s);
  181.           if(fgets3(s,256,i3handle)) {
  182.             cpkt->to = strdup3(s);
  183.             if(fgets3(s,256,i3handle)) {
  184.               cpkt->creator = strdup3(s);
  185.               if(cpkt->creator) {
  186.                 if(fgets3(s,256,i3handle)) {
  187.                   cpkt->pword = strdup3(s);
  188.                   if(fgets3(s,256,i3handle)) {
  189.                     cpkt->area = strdup3(s);
  190.                     if(!(!cpkt->area && !cpkt->to)) {
  191.  
  192.                       while(!eof(i3handle)) {
  193.  
  194.                         char *data;
  195.                         TAG3 *info;
  196.                         TAG3 *here = cpkt->head;
  197.  
  198.                         if(!fgets3(s,256,i3handle)) break;
  199.                         if(!*s) break;      /* end of packet header */
  200.                         data = strchr(s,' ');
  201.                         if(data) {
  202.                           *data = 0;
  203.                           data++;
  204.                           while(*data == ' ' || *data == '\t') data++;
  205.                         }
  206.  
  207.                         /* code dealing with experimental tags goes here */
  208.  
  209.                         if(!strnicmp(s,"X-",2)) continue;  /* then "strip"
  210.                                                             * unrecognized
  211.                                                             * experimental
  212.                                                             * tags */
  213.  
  214.                         info = (TAG3 *)malloc(sizeof(TAG3));
  215.                         if(!info) break;        /* tsk, tsk */
  216.                         info->tag = strdup3(s);
  217.                         if(!info->tag) {
  218.                           free(info);
  219.                           break;
  220.                         }
  221.                         info->data = strdup3(data);
  222.                         if(!cpkt->head) cpkt->head = info;
  223.                         else here->next = info;
  224.                         info->next = NULL;
  225.                         here = info;
  226.                       }
  227.                       *error = NOERR3;
  228.                       return cpkt;   /* success */
  229.  
  230.                     }
  231.                   }
  232.                 }
  233.               }
  234.             }
  235.           }
  236.         }
  237.       }
  238.       else *error = NOMEM3;
  239.     }
  240.   }
  241.  
  242.   if(cpkt) cpkt = free_3pkthdr(cpkt); /* failure */
  243.   return cpkt;
  244. }
  245.  
  246.  
  247.  
  248. long find_next_3msg (int i3handle,int *error) {
  249.  
  250.   /* find the next message in a packet (used when a grunged header is
  251.    * encountered to attempt to resynch
  252.    * just searches for a NUL in the file
  253.    */
  254.  
  255.   char *buf,*p;
  256.   int   len;
  257.   long  pos;
  258.  
  259.   buf = (char *)malloc(BLKSIZE3);
  260.   if(!buf) {
  261.     *error = NOMEM3;
  262.     return -1L;
  263.   }
  264.  
  265.   while(!eof(i3handle)) {
  266.     pos = tell(i3handle);
  267.     len = read(i3handle,buf,BLKSIZE3);
  268.     if(len == -1) {
  269.       *error = READERR3;
  270.       free(buf);
  271.       return -1L;
  272.     }
  273.     if(!len) break;
  274.     p = buf;
  275.     while(p < buf + len) {
  276.       if(!*p) {
  277.         p++;
  278.         lseek (i3handle, pos + ((int)p - (int)buf), SEEK_SET);
  279.         free(buf);
  280.         return tell(i3handle);
  281.       }
  282.       p++;
  283.     }
  284.   }
  285.   *error = EOP3;
  286.   free(buf);
  287.   return -1L;
  288. }
  289.  
  290.  
  291.  
  292. MHDR3 * read_3msghdr (int i3handle, MHDR3 *cmsg, int *error) {
  293.  
  294.   /* could use more error & grunge checking
  295.    * return NULL on error OR EOP
  296.    * *error may contain more info
  297.    * fills in msg header structure cmsg from file represented
  298.    * by file handle i3handle
  299.    */
  300.  
  301.   char        s[257];
  302.   int         tries = 0;
  303.  
  304. ReTry:
  305.  
  306.   *error = EOP3;
  307.   if(cmsg) free_3msghdr(cmsg);
  308.   if(fgets3(s,256,i3handle) && *s) {
  309.     cmsg = create_3msghdr();
  310.     if(cmsg) {
  311.       *error = BADMSGHDR3;
  312.       cmsg->from = strdup3(s);
  313.       if(cmsg->from) {
  314.         if(fgets3(s,256,i3handle)) {
  315.           cmsg->to = strdup3(s);
  316.           if(fgets3(s,256,i3handle)) {
  317.             cmsg->subj = strdup3(s);
  318.             if(fgets3(s,256,i3handle)) {
  319.               cmsg->date = strdup3(s);
  320.               if(cmsg->date) {
  321.                 if(fgets3(s,256,i3handle)) {
  322.                   cmsg->area = strdup3(s);
  323.                   if(fgets3(s,256,i3handle)) {
  324.                     cmsg->id = strdup3(s);
  325.                     if(cmsg->id) {
  326.                       if(fgets3(s,256,i3handle)) {
  327.                         cmsg->ref = strdup3(s);
  328.                         while(!eof(i3handle)) {
  329.  
  330.                           char *data = NULL;
  331.                           TAG3 *info;
  332.                           TAG3 *here = cmsg->head;
  333.  
  334.                           if(!fgets3(s,256,i3handle)) break;
  335.                           if(!*s) break;        /* end of message header */
  336.                           data = strchr(s,' ');
  337.                           if(data) {
  338.                             *data = 0;
  339.                             data++;
  340.                             while(*data == ' ' || *data == '\t') data++;
  341.                           }
  342.  
  343.                           /* code dealing with experimental tags goes here */
  344.  
  345.                           if(!strnicmp(s,"X-",2)) continue;  /* then "strip"
  346.                                                               * unrecognized
  347.                                                               * experimental
  348.                                                               * tags */
  349.  
  350.                           info = (TAG3 *)malloc(sizeof(TAG3));
  351.                           if(!info) break;              /* tsk, tsk */
  352.                           info->tag = strdup3(s);
  353.                           if(!info->tag) {
  354.                             free(info);
  355.                             break;
  356.                           }
  357.                           info->data = strdup3(data);
  358.                           if(!cmsg->head) cmsg->head = info;
  359.                           else here->next = info;
  360.                           info->next = NULL;
  361.                           here = info;
  362.                         }
  363.                         *error = NOERR3;
  364.                         return cmsg;   /* success */
  365.                       }
  366.                     }
  367.                   }
  368.                 }
  369.               }
  370.             }
  371.           }
  372.         }
  373.       }
  374.       if(find_next_3msg(i3handle,error) != -1L && tries++ < MAXRESYNC3)
  375.         goto ReTry;  /* skip to next msg -- goto?  suffer!!! */
  376.     }
  377.     else *error = NOMEM3;
  378.   }
  379.  
  380.   if(cmsg) cmsg = free_3msghdr(cmsg);
  381.   return cmsg;
  382. }
  383.  
  384.  
  385. int read_3msgtext (int i3handle,char *msg, int buflen, int *error) {
  386.  
  387.   /* call until 0 or -1 is returned.  0 = EOM  -1 = EOP
  388.    * i3handle is file handle for packet
  389.    * msg = text buffer
  390.    * buflen = length of buffer
  391.    */
  392.  
  393.   int   bufread = 0;
  394.   long  sizefile,pos;
  395.   char *p;
  396.  
  397.   *error = NOERR3;
  398.   if(!eof(i3handle)) {
  399.     sizefile = filelength(i3handle);
  400.     pos = tell(i3handle);
  401.     if(sizefile > pos)
  402.       bufread = read(i3handle,msg,min(buflen,(int)(sizefile - pos)));
  403.     if(bufread > 0) {
  404.       p = strchr(msg,'\0'); /* EOM marker */
  405.       if(p) {
  406.         p++;
  407.         bufread = (int)p - (int)msg;
  408.         lseek(i3handle,pos + (long)bufread,SEEK_SET);  /* pos to start of next msg */
  409.       }
  410.     }
  411.     else if(bufread == -1) *error = READERR3;
  412.   }
  413.  
  414.   return bufread;
  415. }
  416.  
  417.  
  418. long process_3pkt (void *anon,char *fname,int *error) {
  419.  
  420.   /* process a type 3ASCII packet.  four functions are external ("callback"):
  421.    *
  422.    * int import_3msg(void *anon,PHDR3 *,MHDR3 *,char *text,
  423.    *                 int length,int *error);
  424.    * int appendin_3msg(void *anon,PHDR3 *,MHDR3 *,char *text,
  425.    *                   int length,int *error);
  426.    *
  427.    * these functions should handle import to the message base and
  428.    * export to outgoing packets as required by the bbs/mailer, as
  429.    * well as dupe checking on the message header id field.  return
  430.    * non-zero to abort processing of packet.
  431.    *
  432.    * int check_3pkthdr(void *anon,char *fname,PHDR3 *,int *error);
  433.    *
  434.    * this function should return 0 if the packet should be processed,
  435.    * or anything else to abort processing and return control to caller.
  436.    *
  437.    * int check_3msghdr(void *anon,MHDR3 *,int *error);
  438.    *
  439.    * this function should return 0 if the message should be processed,
  440.    * or anything else to skip it and go for the next message.
  441.    *
  442.    * anon = private data for "callback" functions
  443.    * fname = name of packet to process
  444.    * *error = returned error code
  445.    * returns number of msgs processed
  446.    */
  447.  
  448.   PHDR3 *cpkt = NULL;
  449.   MHDR3 *cmsg = NULL;
  450.   char  *msgtext;
  451.   int   textlen;
  452.   int   i3handle = -1;
  453.   long  nummsgs = 0;
  454.  
  455.   *error = NOERR3;
  456.   msgtext = (char *)malloc(BLKSIZE3 + 1);
  457.   if(msgtext) {
  458.     i3handle = open_3pkt(i3handle,fname,error);
  459.     if(i3handle != -1) {
  460.       cpkt = read_3pkthdr(i3handle,cpkt,error);
  461.       if(cpkt) {
  462.         if(!check_3pkthdr(anon,fname,cpkt,error)) {
  463.           do {
  464.             cmsg = read_3msghdr(i3handle,cmsg,error);
  465.             if(*error) break;
  466.             if(cmsg) {
  467.               textlen = read_3msgtext(i3handle,msgtext,BLKSIZE3,error);
  468.               if(*error) break;
  469.               if(check_3msghdr(anon,cmsg,error)) {
  470.                 *error = NOERR3;
  471.                 if(find_next_3msg(i3handle,error) == -1L) break;
  472.                 continue;
  473.               }
  474.               if(textlen > 0) {
  475.                 nummsgs++;
  476.                 if(import_3msg(anon,cpkt,cmsg,msgtext,textlen,error)) break;
  477.                 while(textlen == BLKSIZE3) {
  478.                   textlen = read_3msgtext(i3handle,msgtext,BLKSIZE3,error);
  479.                   if(*error) break;
  480.                   if(textlen > 0) {
  481.                     if(appendin_3msg(anon,cpkt,cmsg,msgtext,textlen,error)) break;
  482.                   }
  483.                 }
  484. #ifdef TRANSLATING
  485.                 end_3msg(anon,cpkt,cmsg);
  486. #endif
  487.               }
  488.             }
  489.           } while(cmsg);
  490.         }
  491.       }
  492.       i3handle = close_3pkt(i3handle);
  493.     }
  494.   }
  495.   else *error = NOMEM3;
  496.  
  497.   if(cpkt) free_3pkthdr(cpkt);
  498.   if(cmsg) free_3msghdr(cmsg);
  499.   if(msgtext) free(msgtext);
  500.  
  501.   return nummsgs;
  502. }
  503.